package com.wn.aop;



import com.wn.annotation.RequireRoles;
import com.wn.utils.JwtUtil;
import com.wn.utils.Rsp;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Arrays;

/**
 * @Retention(RetentionPolicy.RUNTIME)
 * @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
 * @Documented
 * public @interface Order {
 *
 * 	/**
 * 	 * 默认是最低优先级,值越小优先级越高
 *          * 	int value() default Ordered.LOWEST_PRECEDENCE;
    }

 业务服务器根据自己的业务规则 制定配套的权限校验规则

 */
@Aspect
@Component
@Order(-100)
public class AuthAspect {


    private static Logger log = LoggerFactory.getLogger(AuthAspect.class);


    //设置切点 类型是一个方法体为空 无返回值 的方法  传入注解对象为参数
    @Pointcut("@annotation(requireRoles)")
    public void AuthService(RequireRoles requireRoles){}


    //切面处理方法 采用环绕型通知方法 传入上面配置的切点信息
    @Around("AuthService(requireRoles)")
    public Object doAroud(ProceedingJoinPoint joinPoint,RequireRoles requireRoles) throws Throwable {

        //获取我们注解中配置的角色信息 返回的是roleSign数组
        String [] roles = requireRoles.roles();

        //获取注解中的index,该变量标识token这个参数的位置
        int index = requireRoles.index();

        //获取请求参数中的token
        String token  = (String) joinPoint.getArgs()[index];
        //获取实体类对象
        Object obj = joinPoint.getArgs()[index-1];

        //解析token中的用户信息
        String userId = JwtUtil.parseToken(token).get("id").asString();
        //获取实体类对象的字节码信息
        Class<?> c = obj.getClass();
        //判断对象的数据类型
        if(!c.getSimpleName().equals("PageParam")){
            // 获取该类的成员变量
            Field f = c.getDeclaredField("createuserid");
            Field f1 = c.getDeclaredField("updatauserid");
            // 取消语言访问检查
            f.setAccessible(true);
            f1.setAccessible(true);
            // 给变量赋值
            f.set(obj, userId);
            f1.set(obj, userId);
            System.out.println("********************");
            System.out.println(obj);
        }

        //拿到当前对象的角色标记
        String roleSign = JwtUtil.parseToken(token).get("roleSign").asString();

        //权限校验
        if(Arrays.asList(roles).contains(roleSign)){
            //如果注解中的角色id包含 这次请求中角色的id  就放行 继续执行后面的操作
            return joinPoint.proceed();
        }else{
            //如果不包含 则返回权限不足的错误提示
            return Rsp.fail().msg("权限不足");
        }


    }


}
